package logger

import (
	"go-kit-service/pkg/config"
	"os"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	lumberjack "gopkg.in/natefinch/lumberjack.v2"
)

var logger *zap.Logger

func Initialize() {
	logConfig := config.C.Log

	// 配置输出
	var ws = []zapcore.WriteSyncer{}
	if logConfig.Output.File {
		hook := lumberjack.Logger{
			Filename:   logConfig.Output.FilePath,        // 日志文件路径
			MaxSize:    int(logConfig.Output.MaxSize),    // 每个日志文件保存的最大尺寸 单位：M
			MaxBackups: int(logConfig.Output.MaxBackups), // 日志文件最多保存多少个备份
			MaxAge:     int(logConfig.Output.MaxAge),     // 文件最多保存多少天
			Compress:   logConfig.Output.Compress,        // 是否压缩
		}
		ws = append(ws, zapcore.AddSync(&hook))
	}
	if config.C.Log.Output.Console {
		ws = append(ws, zapcore.AddSync(os.Stdout))
	}

	// 配置Encoder
	config := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "line",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		EncodeLevel:    zapcore.LowercaseLevelEncoder,  // 编码级别
		EncodeTime:     zapcore.RFC3339TimeEncoder,     // 日期格式
		EncodeDuration: zapcore.SecondsDurationEncoder, //
		EncodeCaller:   zapcore.ShortCallerEncoder,     // 路径编码器
	}

	// 设置日志级别
	var level = zap.NewAtomicLevel()
	if f := level.UnmarshalText([]byte(logConfig.Level)); f != nil {
		level.SetLevel(zap.InfoLevel)
	}

	// 设置格式
	var format zapcore.Encoder
	if logConfig.Context.Format == "json" {
		format = zapcore.NewJSONEncoder(config)
	} else {
		format = zapcore.NewConsoleEncoder(config)
	}

	// 初始化日志
	core := zapcore.NewCore(format, zapcore.NewMultiWriteSyncer(ws...), level)

	// 设置初始化字段
	var fields []zapcore.Field
	for k, v := range logConfig.Context.Fileds {
		fields = append(fields, zap.String(k, v))
	}

	// 构造日志记录器
	opts := make([]zap.Option, 0, 3)
	opts = append(opts, zap.Fields(fields...))
	if logConfig.Context.ShowCaller {
		opts = append(opts, zap.AddCaller(), zap.AddCallerSkip(1))
	}

	logger = zap.New(core, opts...)
}

func Debug(msg string, fields ...zapcore.Field) {
	logger.Debug(msg, fields...)
}

func Info(msg string, fields ...zapcore.Field) {
	logger.Info(msg, fields...)
}

func Warn(msg string, fields ...zapcore.Field) {
	logger.Warn(msg, fields...)
}

func Error(msg string, fields ...zapcore.Field) {
	logger.Error(msg, fields...)
}

func DPanic(msg string, fields ...zapcore.Field) {
	logger.DPanic(msg, fields...)
}

func Panic(msg string, fields ...zapcore.Field) {
	logger.Panic(msg, fields...)
}

func Fatal(msg string, fields ...zapcore.Field) {
	logger.Fatal(msg, fields...)
}

func Sync() error {
	return logger.Sync()
}
